package meta.api.web.common.presentation;

import org.apache.catalina.connector.ClientAbortException;
import org.springframework.dao.DataAccessException;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.TransactionException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import jakarta.servlet.http.HttpServletRequest;
import meta.common.exception.CmnSysException;
import meta.common.log.CmnLogger;
import meta.common.msg.Message;
import meta.common.msg.MessageConst;
import meta.common.util.MsgUtil;

@ControllerAdvice
public class GlobalErrorAdvice {

    private CmnLogger logger = CmnLogger.getLogger(this.getClass());

    public static final String ERROR_MSG = "errorMsg";

    @ExceptionHandler(DataAccessException.class)
    public String handleDataAccessException(DataAccessException e, HttpServletRequest req) {
        Message errorMessage = new Message(MessageConst.MSG_01020002, MsgUtil.dbErrorMsgCheck(e));
        return forwardError(errorMessage, req, e);
    }

    @ExceptionHandler(TransactionException.class)
    public String handleTransactionException(TransactionException e, HttpServletRequest req) {
        Message errorMessage = null;
        if (e instanceof CannotCreateTransactionException &&
            e.getCause() != null && e.getCause().getMessage() != null &&
            e.getCause().getMessage().equals("Cannot get a connection, pool error Timeout waiting for idle object")) {
            errorMessage = new Message(MessageConst.MSG_01020004, MsgUtil.dbErrorMsgCheck(e));
        } else {
            errorMessage = new Message(MessageConst.MSG_01020001, MsgUtil.dbErrorMsgCheck(e));
        }
        return forwardError(errorMessage, req, e);
    }

    @ExceptionHandler(ClientAbortException.class)
    public String handleClientAboutException(ClientAbortException e, HttpServletRequest req) {
        logger.log(MessageConst.MSG_01050001, null, e);
        return null;
    }

    @ExceptionHandler(CmnSysException.class)
    public String handleCmnSysException(CmnSysException e, HttpServletRequest req) {
        return forwardError(e.getMsg(), req, e);
    }

    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, HttpServletRequest req) {
        Message errorMessage = new Message(MessageConst.MSG_01090001, null);;
        return forwardError(errorMessage, req, e);
    }

    private String forwardError(Message errorMessage, HttpServletRequest req, Throwable t) {
        logger.log(errorMessage, t);
        req.setAttribute(ERROR_MSG, errorMessage.getMsgContent());
        return "forward:/error.json";
    }
}
